<?php

declare(strict_types=1);

namespace app\controller\system;

use app\BaseController;
use app\model\AuthRole;
use app\service\factory\ResponseFactory;
use app\service\sys\RoleService;
use app\validate\system\SysRoleValidate;
use InvalidArgumentException;
use think\Response;
use Throwable;

class Role extends BaseController
{
    public function index(RoleService $roleService): Response
    {
        try {
            $page = max(1, (int) $this->request->param('page', 1));
            $pageSize = (int) $this->request->param('page_size', 20);
            $pageSize = $pageSize > 0 ? min($pageSize, 100) : 20;

            $filters = $this->request->only([
                'keyword',
                'status',
                'scope_type',
            ], 'get');

            $paginator = $roleService->paginate($filters, $page, $pageSize);
            $list = $roleService->formatCollection($paginator->items());

            return json(ResponseFactory::paginated(
                $list,
                (int) $paginator->total(),
                $page,
                $pageSize
            ));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }

    public function read(int $id, RoleService $roleService): Response
    {
        try {
            $role = $roleService->findById($id);
            if (!$role) {
                return json(ResponseFactory::error('角色不存在', 404));
            }

            return json(ResponseFactory::success($roleService->format($role)));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }

    public function save(RoleService $roleService): Response
    {
        try {
            $payload = $this->request->only([
                'name',
                'slug',
                'scope_type',
                'description',
                'status',
                'permission_ids',
            ], 'post');

            $this->validate($payload, SysRoleValidate::class . '.create');

            $role = $roleService->create($payload);

            return json(ResponseFactory::success($roleService->format($role), '角色已创建'));
        } catch (InvalidArgumentException $e) {
            return json(ResponseFactory::error($e->getMessage(), 422));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }

    public function update(int $id, RoleService $roleService): Response
    {
        try {
            $role = AuthRole::find($id);
            if (!$role) {
                return json(ResponseFactory::error('角色不存在', 404));
            }

            $payload = $this->request->only([
                'name',
                'slug',
                'scope_type',
                'description',
                'status',
                'permission_ids',
            ], 'put');
            $payload['id'] = $id;

            $validatePayload = $payload;
            if (!array_key_exists('name', $validatePayload)) {
                $validatePayload['name'] = $role->name;
            }
            if (!array_key_exists('slug', $validatePayload)) {
                $validatePayload['slug'] = $role->slug;
            }
            if (!array_key_exists('scope_type', $validatePayload)) {
                $validatePayload['scope_type'] = $role->scope_type;
            }
            if (!array_key_exists('description', $validatePayload)) {
                $validatePayload['description'] = (string) $role->description;
            }
            if (!array_key_exists('status', $validatePayload)) {
                $validatePayload['status'] = (int) $role->status;
            }

            $this->validate($validatePayload, SysRoleValidate::class . '.update');

            $updated = $roleService->update($role, $payload);

            return json(ResponseFactory::success($roleService->format($updated), '角色已更新'));
        } catch (InvalidArgumentException $e) {
            return json(ResponseFactory::error($e->getMessage(), 422));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }

    public function delete(int $id, RoleService $roleService): Response
    {
        try {
            $role = AuthRole::find($id);
            if (!$role) {
                return json(ResponseFactory::error('角色不存在', 404));
            }

            if (!$roleService->delete($role)) {
                return json(ResponseFactory::error('删除失败', 500));
            }

            return json(ResponseFactory::success(true, '角色已删除'));
        } catch (InvalidArgumentException $e) {
            return json(ResponseFactory::error($e->getMessage(), 422));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }
}
